/**
@author		Jong Min, Lee
@date		  02/06/2014
@brief		toolbox class

copyright(c) Tae Young Soft. All right reserved. 2014
*/
#pragma once

#include <list>

#include "Taurus_Util/TUTypes.h"
#include "Taurus_ToolData/ToolData.h"
#include "Taurus_Viewer/TBLayoutInfo.h"
#include "Taurus_Util/Macros.h"

//forward declarations
class CToolButton;
class CToolboxData;

/**
@brief		toolbox class that displays tool buttons
*/
class CToolbox : public CWnd
{
  DECLARE_DYNAMIC(CToolbox)

private:
  DISALLOW_COPY_AND_ASSIGN(CToolbox);

public:
  typedef struct tagCreateParams
  {
    tagCreateParams()
      : enumResType(MonitorResolution_Normal)
      , bEnableNotification(TRUE)
    {
    }

    MonitorResolutionType enumResType;
    BOOL                  bEnableNotification;
  }CreateParams;

public:
  /**
  @brief		default constructor
  */
  CToolbox();

  /**
  @brief		destructor
  */
  virtual ~CToolbox();

  /**
  @brief		get index number of tool button that contains specified point
  @param		pt the point to be checked
  @param    index variable in which the index number is stored
  @return		ERROR_SUCCESS if succeeds, an error code otherwise
  */
  DWORD getToolIndex(const CPoint& pt, unsigned& index) const;

  /**
  @brief		insert a tool at specified index
  @param		index index number in tool button container where new tool is inserted
  @param    pToolData pointer to tool data be inserted
  @return		ERROR_SUCCESS upon success, an error code otherwise
  */
  DWORD insertToolAt(const unsigned index, const CToolData* pToolData);

  /**
  @brief		add a tool data
  @param		pToolData pointer to tool data to be added
  @return		ERROR_SUCCESS if succeeds, an error code otherwise
  */
  DWORD addTool(const CToolData* pToolData);

  /**
  @brief		open toolbox data
  @param    pToolboxData pointer to toolbox data to be open
  @param    bRedraw flag indicating whether toolbox is to be redraw
  @return		ERROR_SUCCESS if succeeds, an error code otherwise
  */
  DWORD openToolbox(const CToolboxData* pToolboxData);

  /**
  @brief		find a tool button by using ID and make it selected
  @param		uID tool ID
  @return		ERROR_SUCCESS if succeeds, an error code otherwise
  */
  DWORD selectTool(UINT uID);

  /**
  @brief		find a tool button by using ID and make it enable or disable
  @param		uID tool ID
  @param    bEnable flag indicating whether tool button should be enable or disable
  @return		ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD enableTool(UINT uID, BOOL bEnable);

  /**
  @brief		enable or disable all tool buttons
  @param		bEnable flag indicating whether all tool buttons should be enable or disable
  */
  void enableAllTools(BOOL bEnable);

  /**
  @brief		find a tool button by index number and remove it.
  @param		index the index number of tool to be removed
  @return		ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD removeTool(unsigned index);

  /**
  @brief		remove all tool buttons
  @param		bRedraw flag indicating whether toolbox is to be redrawn
  */
  void removeAllTools();

  /**
  @brief		get number of tool buttons that displayed in toolbox
  @return		the number of tool buttons
  */
  inline unsigned getNumTools() const
  {
    return m_listToolButtons.size();
  }

  /**
  @brief		lock rearrange operation
  */
  void lockRearrange();

  /**
  @brief	  release rearrange operation lock
  */
  void releaseRearrange();

private:
  /**
  @brief		rearrange tool buttons
  */
  void rearrangeButtons();

  /**
  @brief		rearrange tool buttons vertically
  */
  void rearrangeButtonsV();

  /**
  @brief		rearrange tool buttons horizontally
  */
  void rearrangeButtonsH();

  /**
  @brief		get tool button margin
  @param		enumResType monitor resolution type
  @param    bVertical flag indicating whether toolbox is vertical or horizontal
  @param    csMargin variable in which left and top margins are stored
  */
  void getToolButtonMargin(MonitorResolutionType enumResType,
                           BOOL bVertical,
                           CSize& csMargin);

  /**
  @brief		get tool button size
  @param		enumResType monitor resolution type
  @param    bVertical flag indicating toolbox is vertical or horizontal
  @param    csSize variable in which tool button size is stored
  */
  void getToolButtonSize(MonitorResolutionType enumResType,
                         BOOL bVertical,
                         CSize& csSize);

  /**
  @brief		create the Windows button control and attach it to the tool button
  @param		pToolButton pointer to tool button
  @return		ERROR_SUCCESS if succeeds, an error code otherwise
  */
  DWORD createToolButton(CToolButton* pToolButton);

  /**
  @brief		create the Windows button controls and attach them to all tool buttons
  @return		ERROR_SUCCESS if succeeds, an error code otherwise
  */
  DWORD createAllToolButtons();

  /**
  @brief		destroy the Window button control attached to all tool buttons
  */
  void destroyAllToolButtons();

  /**
  @brief		validate create parameters 
  @param		pointer to create params
  @return		TRUE if legal, FALSE otherwise
  */
  BOOL validateCreateParams(const CreateParams* pParams) const;

private:
  //tool buttons
  std::list<CToolButton*> m_listToolButtons;

  //monitor resolution type
  MonitorResolutionType m_enumResType;

  //flag indicating notify or not when tool button is clicked
  BOOL m_bEnableNotification;

  //flag indicating rearrange tool buttons when toolbox should repaint
  BOOL m_bMuseRearrange;

  //flag indicating rearrange operation is locked
  BOOL m_bIsRearrangeLocked;

protected:
  DECLARE_MESSAGE_MAP()

  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  afx_msg void OnPaint();
  afx_msg BOOL OnEraseBkgnd(CDC* pDC);
  afx_msg void OnSize(UINT nType, int cx, int cy);
  virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
};